package com.hyny.framework.platform.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;

import com.hyny.framework.platform.system.entity.dto.LoginRoleFieldPowerDTO;
import com.hyny.framework.platform.system.entity.dto.LoginUserDataPowerDTO;
import com.hyny.framework.platform.system.entity.dto.RoleFieldPowerDTO;
import com.hyny.framework.platform.system.entity.pojo.*;
import com.hyny.framework.platform.system.entity.vo.LoginUserVO;
import com.hyny.framework.platform.system.entity.vo.LoginVO;
import com.hyny.framework.platform.system.service.SysUserDataPowerService;
import com.hyny.framework.platform.system.service.SysUserRoleService;
import com.hyny.framework.platform.system.service.SysUserService;
import com.hyny.framework.platform.system.service.SysRoleMenuService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysUserRoleService sysUserRoleService;
    @Autowired
    private SysUserDataPowerService sysUserDataPowerService;
    @Autowired
    private SysRoleMenuService sysRoleMenuService;


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //获取用户信息
        SysUser sysUser = sysUserService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserName, username));
        if (sysUser == null) {
            throw new InternalAuthenticationServiceException("用户不存在");
        }

        //获取角色信息
        List<String> roles = getRoles(sysUser.getId());

        //获取功能权限
        List<String> permissions = getPpermissions(roles);
        //获取角色字段权限
        List<LoginRoleFieldPowerDTO> loginRoleFieldPowerDTOS=getLoginRoleFieldPowerDTO( roles);
        //获取用户数据权限
        LoginUserDataPowerDTO loginUserDataPowerDTOS= getLoginUserDataPowerDTOS(sysUser.getId());

        return new LoginVO(BeanUtil.copyProperties(sysUser, LoginUserVO.class), permissions, roles, loginUserDataPowerDTOS, loginRoleFieldPowerDTOS);
    }


    /**
     * 获取角色id
     *
     * @param userid
     * @return
     */
    public List<String> getRoles(Long userid) {
        //获取角色
        MPJLambdaWrapper<SysUserRole> roleMPJLambdaWrapper = new MPJLambdaWrapper<>();
        roleMPJLambdaWrapper.select(SysUserRole::getRoleId);
        roleMPJLambdaWrapper.eq(SysUserRole::getUserId, userid);
        List<String> roles = sysUserRoleService.selectJoinList(String.class, roleMPJLambdaWrapper);
        return roles;
    }


    /**
     * 获取功能权限
     *
     * @param roles
     * @return
     */
    public List<String> getPpermissions(List<String> roles) {
        MPJLambdaWrapper<SysRoleMenu> menuMPJLambdaWrapper = new MPJLambdaWrapper<>();
        menuMPJLambdaWrapper.select(SysMenu::getPermissions);
        menuMPJLambdaWrapper.leftJoin(SysMenu.class, SysMenu::getId, SysRoleMenu::getMenuId);
        menuMPJLambdaWrapper.isNotNull(SysMenu::getPermissions);
        menuMPJLambdaWrapper.ne(SysMenu::getPermissions, "");
        menuMPJLambdaWrapper.in(SysRoleMenu::getRoleId, roles);
        menuMPJLambdaWrapper.groupBy(SysRoleMenu::getMenuId);
        List<String> permissions = sysRoleMenuService.selectJoinList(String.class, menuMPJLambdaWrapper);
        return permissions;
    }


    /**
     * 根据角色获取字段信息
     * @param roles
     * @return
     */
    public List<LoginRoleFieldPowerDTO> getLoginRoleFieldPowerDTO(List<String> roles) {
        MPJLambdaWrapper<SysRoleMenu> roleMenuMPJLambdaWrapper = new MPJLambdaWrapper<>();
        roleMenuMPJLambdaWrapper.leftJoin(SysMenu.class, SysMenu::getId, SysRoleMenu::getMenuId);
        roleMenuMPJLambdaWrapper.leftJoin(SysRoleFieldPower.class, SysRoleFieldPower::getRoleId, SysRoleMenu::getRoleId);
        roleMenuMPJLambdaWrapper.leftJoin(SysFieldPower.class, SysFieldPower::getId, SysRoleFieldPower::getFieldPowerId);
        roleMenuMPJLambdaWrapper.selectAs(SysMenu::getRequestUrl, RoleFieldPowerDTO::getRequestUrl);
        roleMenuMPJLambdaWrapper.selectAs(SysFieldPower::getFieldName, RoleFieldPowerDTO::getFieldName);
        roleMenuMPJLambdaWrapper.selectAs(SysFieldPower::getFieldTitle, RoleFieldPowerDTO::getFieldTitle);


        roleMenuMPJLambdaWrapper.in(SysRoleMenu::getRoleId, roles);
        roleMenuMPJLambdaWrapper.isNotNull(SysMenu::getRequestUrl);
        roleMenuMPJLambdaWrapper.isNotNull(SysFieldPower::getFieldName);
        List<RoleFieldPowerDTO> roleFieldPowerDTOS = sysRoleMenuService.selectJoinList(RoleFieldPowerDTO.class, roleMenuMPJLambdaWrapper);

        List<LoginRoleFieldPowerDTO> loginRoleFieldPowerDTOS = new ArrayList<>();

        //根据项目标识过滤
        Map<String, List<RoleFieldPowerDTO>> groupProjectPermissionsMap = roleFieldPowerDTOS.stream().collect(Collectors.groupingBy(RoleFieldPowerDTO::getProjectPermissions));

        //循环项目相关信息
        for (Map.Entry<String, List<RoleFieldPowerDTO>> entryProjectPermissions : groupProjectPermissionsMap.entrySet()) {
            LoginRoleFieldPowerDTO loginRoleFieldPowerDTO = new LoginRoleFieldPowerDTO();
            loginRoleFieldPowerDTO.setProjectPermissions(entryProjectPermissions.getKey());
            //根据接口过滤
            Map<String, List<RoleFieldPowerDTO>> groupRequestUrlMap = entryProjectPermissions.getValue().stream().collect(Collectors.groupingBy(RoleFieldPowerDTO::getRequestUrl));
            List<LoginRoleFieldPowerDTO.RequestUrl> requestUrls = new ArrayList<>();
            //循环接口
            for (Map.Entry<String, List<RoleFieldPowerDTO>> entryRequestUrl : groupRequestUrlMap.entrySet()) {
                LoginRoleFieldPowerDTO.RequestUrl requestUrl = loginRoleFieldPowerDTO.new RequestUrl();
                requestUrl.setRequestUrl(entryRequestUrl.getKey());
                List<LoginRoleFieldPowerDTO.Field> fields = new ArrayList<>();
                //循环字段
                for (RoleFieldPowerDTO entryField : entryRequestUrl.getValue()) {
                    LoginRoleFieldPowerDTO.Field field = loginRoleFieldPowerDTO.new Field();
                    field.setFieldName(entryField.getFieldName());
                    field.setFieldTitle(entryField.getFieldTitle());
                    fields.add(field);
                }
                requestUrl.setFields(fields);
                requestUrls.add(requestUrl);
            }
            loginRoleFieldPowerDTO.setRequestUrls(requestUrls);
            loginRoleFieldPowerDTOS.add(loginRoleFieldPowerDTO);
        }


        return loginRoleFieldPowerDTOS;

    }


    /**
     * 获取用户数据权限
     * @param userid
     * @return
     */
    public  LoginUserDataPowerDTO getLoginUserDataPowerDTOS(Long userid){
        LoginUserDataPowerDTO loginUserDataPowerDTO = new LoginUserDataPowerDTO();
        //获取用户数据权限
        List<SysUserDataPower> userDataPowers = sysUserDataPowerService.list(new LambdaQueryWrapper<SysUserDataPower>()
                .eq(SysUserDataPower::getUserId, userid));
        Map<String, List<String>> dataPowerList=new HashMap<>();

        for (SysUserDataPower sysUserDataPower : userDataPowers
        ) {
            if(!dataPowerList.containsKey(sysUserDataPower.getFieldName())){
                dataPowerList.put(sysUserDataPower.getFieldName(),new ArrayList<>());
            }
            dataPowerList.get(sysUserDataPower.getFieldName()).add(sysUserDataPower.getDataValue());
        }
        loginUserDataPowerDTO.setDataPowerList(dataPowerList);
        return loginUserDataPowerDTO;
    }

}
